from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin, ModelViewSet
from rest_framework.views import APIView
from oauth2_provider.contrib.rest_framework import TokenHasScope

from prj005.serializers import (
    ClinicalLinkSerializer, CureLinkSerializer, HistoryLinkSerializer,
    InfoLinkSerializer, RelevantLinkSerializer, SummaryLinkSerializer,
    ResultLinkSerializer, CheckStatusSerializer, InfoSerializer,
    SearchSerializer, MobileSerializer
)
from prj005.models import (
    clinical, cure, history, info,
    relevant, result, summary
)
from prj005.permissions import MainPermissions, MobileClientPermission
from prj005.utils.sameviews import MainSameView, SearchInfoView
from prj005.utils.func import get_excel_needed
from prj005.utils.constants import SESSION_DATA
from prj005.pagination import ListInfoPagination

from utils.samecode import deny_check, SCChartView, func_pop_none_value
from utils.saveexcel import create_excel
from celery_tasks import tasks


class MobileView(ModelViewSet):
    permission_classes = [TokenHasScope, MobileClientPermission]
    required_scopes = ['prj005']
    serializer_class = MobileSerializer

    def create(self, request, *args, **kwargs):
        data = request.data
        require_key = [
            'clinical', 'cure', 'history', 'info',
            'relevant', 'result', 'summary'
        ]
        validate_data = func_pop_none_value(data, require_key)

        try:
            serializer = self.get_serializer(data=validate_data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
        except Exception as e:
            return Response({'detail': '信息保存失败', 'error': '{}'.format(e)}, status=400)

        return Response({'detail': '信息保存成功'})


class ChartInfoView(ViewSetMixin, APIView, SCChartView):
    permission_classes = [TokenHasScope, MainPermissions]
    required_scopes = ['prj005']
    model_ = info.Info


class SearchView(SearchInfoView):
    """
    Override .get_queryset() to get instances
    """
    serializer_class = SearchSerializer
    queryset = info.Info.objects.order_by('-create_time', '-serial')

    def get_queryset(self):
        request_data = self.request.data

        SESSION_DATA['{}'.format(self.request.user.id)] = request_data

        self.serializer_class = InfoLinkSerializer

        return self.search_instances(request_data)


class FileOutView(SearchInfoView):
    serializer_class = InfoSerializer
    queryset = info.Info.objects.order_by('-create_time', '-serial')
    pagination_class = None

    def list(self, request, *args, **kwargs):
        search_data = SESSION_DATA.get('{}'.format(request.user.id))

        if not search_data:
            queryset = self.get_queryset()
        else:
            queryset = self.search_instances(search_data)

        total_data = []

        for obj in queryset:
            obj_data = get_excel_needed(obj)
            total_data.append(obj_data)

        file_url = create_excel(total_data, request.user.id, project_name='prj005')

        return Response({'url': file_url})


class InfoView(MainSameView):
    view_name = 'info'
    serializer_class = InfoLinkSerializer
    pagination_class = ListInfoPagination
    queryset = info.Info.objects.order_by('-create_time', '-serial')
    set_session_data = True

    def get_serializer_class(self):
        if self.action == 'check':
            return CheckStatusSerializer

        return self.serializer_class

    @action(detail=True, methods=['post'])
    def check(self, request, pk, *args, **kwargs):
        try:
            info_object = info.Info.objects.get(pk=pk)
        except info.Info.DoesNotExist:
            return Response({'detail': '该记录不存在'}, status=404)

        data = request.data
        before_status = info_object.check_status
        after_status = data.get('check_status')
        user = request.user
        info_user = info_object.owner

        deny_check(before_status, user, after_status, info_user, project_name='prj005')

        for key, value in data.items():
            if hasattr(info_object, key):
                setattr(info_object, key, value)

        info_object.save()

        # celery 处理
        # 1. 未提交 => 已提交: 保存Excel
        if before_status == '未提交' and after_status == '已提交':
            excel_data = get_excel_needed(info_object)
            tasks.celery_save_excel.delay(excel_data, info_object.owner.email, serial=info_object.serial, project_name='prj005')

        # 2. 审核不通过 => 已提交: 保存至数据库

        # self.get_serializer => check status serializer class
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        # self.serializer_class => info serializer class
        info_serializer = self.serializer_class(info_object, context={'request': request})
        return Response(info_serializer.data)


class ClinicalView(MainSameView):
    serializer_class = ClinicalLinkSerializer
    queryset = clinical.Clinical.objects.order_by('-create_time', '-pk')


class CureView(MainSameView):
    serializer_class = CureLinkSerializer
    queryset = cure.Cure.objects.order_by('-create_time', '-pk')


class HistoryView(MainSameView):
    serializer_class = HistoryLinkSerializer
    queryset = history.History.objects.order_by('-create_time', '-pk')


class RelevantView(MainSameView):
    serializer_class = RelevantLinkSerializer
    queryset = relevant.Relevant.objects.order_by('-create_time', '-pk')


class ResultView(MainSameView):
    serializer_class = ResultLinkSerializer
    queryset = result.Result.objects.order_by('-create_time', '-pk')


class SummaryView(MainSameView):
    serializer_class = SummaryLinkSerializer
    queryset = summary.Summary.objects.order_by('-create_time', '-pk')
